/**
 *
 * \file File.h
 *	\brief File definition class
 * \author Edouard ROGE
 * \date 15 septembre 2010
 *
 */

#ifndef _FILE_
#define _FILE_

#include <mutex>
#include <string>
#include <stdio.h>
#include "URI.h"
#include "Core/Memory/HeapObject.h"

namespace Core
{
	namespace File
	{
		/**
		 * \enum eFile
		 * \brief flag about the file
		 */
		enum eFile
		{
			/** Read mode */
			eFile_Read = 1 << 0,
			/** Write mode, if the file already exists, it will be erased */
			eFile_Write = 1 << 1,
			/** Append mode, if the file already exists, it will write from the end of it */
			eFile_Append = 1 << 2,
			/** write or read in text mode (default) */
			eFile_Text = 1 << 3,
			/** write or read in binary mode */
			eFile_Binary = 1 << 4
		};

		/**
		 * \class File
		 * File object with all functions to read / write in binary / text mode
		 */
		class File : public Memory::HeapObject
		{
		public:
			/**
			 * \fn File();
			 * Default constructor
			 */
			File();

			/**
			 * \fn File(const std::string & _strURI);
			 * \param _strURI the URI of the file
			 */
			File(const std::string & _strURI);

			/**
			 * \fn File(const URI & _URI);
			 * \param _URI the URI of the file
			 */
			File(const URI & _URI);

			/**
			 * \fn File(const File & _file);
			 * \param _file file to copy
			 * \brief Copy constructor
			 */
			File(const File & _file);

			/**
			 * \fn File(char * _strURI);
			 * \param _strURI the URI of the file
			 */
			File(char * _strURI);

			/**
			 * \fn File(const char * _strURI);
			 * \param _strURI the URI of the file
			 */
			File(const char * _strURI);

			/**
			 * \fn ~File();
			 * Destructor
			 */
			~File();

			/**
			 * \fn const URI & GetURI() const;
			 * \return the URI of the file
			 */
			const URI & GetURI() const { return m_URI; }

			/**
			 * \fn bool Open( const std::string & _strURI, uint32 _iFileFlags );
			 * \param _strURI URI of the file
			 * \param _iFileFlags flags to open the file, see \enum eFile
			 * \return true if the file is correctly opened
			 */
			bool Open(const std::string & _strURI, uint32 _iFileFlags);

			/**
			 * \fn bool Open( uint32 _iFileFlags );
			 * \param _iFileFlags flags to open the file, see \enum eFile
			 * \return true if the file is correctly opened
			 */
			bool Open(uint32 _iFileFlags);

			/**
			 * \fn bool Close();
			 * \return true if the file is correctly closed
			 */
			bool Close();

			/**
			 * \fn bool IsFlagged(uint32 _iFlags) const;
			 * \param _iFlags flag to test
			 * \return true if the flag in param is set
			 */
			bool IsFlagged(uint32 _iFlags) const;

			/**
			 * \fn bool ReadLine(std::string & _str);
			 * \param _str std::string
			 * \return false if it's the last line of the file (EOF char)
			 */
			bool ReadLine(std::string & _str);

			/**
			 * \fn File & operator >> (int32 & _i);
			 * \param _i variable to fill
			 * \return (*this)
			 */
			File & operator >> (int32 & _i);

			/**
			 * \fn File & operator >> (uint32 & _i);
			 * \param _i variable to fill
			 * \return (*this)
			 */
			File & operator >> (uint32 & _i);

			/**
			 * \fn File & operator >> (float & _f);
			 * \param _f variable to fill
			 * \return (*this)
			 */
			File & operator >> (float & _f);

			/**
			 * \fn File & operator >> (double & _d);
			 * \param _d variable to fill
			 * \return (*this)
			 */
			File & operator >> (double & _d);

			/**
			 * \fn File & operator >> (char & _c);
			 * \param _c variable to fill
			 * \return (*this)
			 */
			File & operator >> (char & _c);

			/**
			* \fn void Read(char * _str, uint32 _iSize);
			* \param _str variable to write into the file
			* \param _iSize size of the string _str
			*/
			void Read(char * _str, uint32 _iSize);

			/**
			* \fn template<class T> File & Read(const T & _value);
			* \param _value variable to write into the file
			*/
			template<class T> File & Read(const T & _value);

			/**
			 * \fn void Write(const char * _fmt, ...);
			 * \param _fmt format of std::string
			 * \param ... parameters
			 */
			void Write(const char * _fmt, ...);

			/**
			 * \fn File & operator << (int32 _i);
			 * \param _i variable to write into the file
			 * \return (*this)
			 */
			File & operator << (int32 _i);

			/**
			 * \fn File & operator << (uint32 _i);
			 * \param _i variable to write into the file
			 * \return (*this)
			 */
			File & operator << (uint32 _i);

			/**
			 * \fn File & operator << (float _f);
			 * \param _f variable to write into the file
			 * \return (*this)
			 */
			File & operator << (float _f);

			/**
			 * \fn File & operator << (double _d);
			 * \param _d variable to write into the file
			 * \return (*this)
			 */
			File & operator << (double _d);

			/**
			 * \fn File & operator << (char _c);
			 * \param _c variable to write into the file
			 * \return (*this)
			 */
			File & operator << (char _c);

			/**
			 * \fn File & operator << (const std::string & _str);
			 * \param _str variable to write into the file
			 * \return (*this)
			 */
			File & operator << (const std::string & _str);

			/**
			* \fn void Write(char * _str, uint32 _iSize);
			* \param _str variable to write into the file
			* \param _iSize size of the string _str
			*/
			void Write(char * _str, uint32 _iSize);

			/**
			* \fn void Write(const char * _str, uint32 _iSize);
			* \param _str variable to write into the file
			* \param _iSize size of the string _str
			*/
			void Write(const char * _str, uint32 _iSize);

			/**
			* \fn template<class T> File & Write(const T & _value);
			* \param _value variable to write into the file
			*/
			template<class T> File & Write(const T & _value);

			/** End of file constant */
			static const int32 EndOfFile = -1;

		private:
			/**
			 * \enum eFile
			 * \brief flag about the file
			 */
			enum eFile
			{
				/** File is opened */
				eFile_Open = 1 << 5
			};

			/** flags see \enum eFile */
			uint32 m_iFlags;

			/** the File object */
			FILE * m_pFile;

			/** URI of the file */
			URI m_URI;

			/** Mutex */
			std::mutex m_mutex;

			/** Size of the buffer to read / write char * */
			static uint32 ms_iBufferSize;
		};

	}
}

#endif //_FILE_
